<!doctype html>
<html lang="zh-CN">
<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Seata总结 | Jeremy Sze的博客</title>
    <meta property="og:title" content="Seata总结 - Jeremy Sze的博客">
    <meta property="og:type" content="article">
        
    <meta property="article:published_time" content='2022-10-06T10:00:54&#43;08:00'>
        
        
    <meta property="article:modified_time" content='2022-10-06T10:00:54&#43;08:00'>
        
    <meta name="Keywords" content="java,博客">
    <meta name="description" content="Seata总结">
        
    <meta name="author" content="Jeremy Sze">
    <meta property="og:url" content="https://laoer123.gitee.io/laoer123/post/Seata%E6%80%BB%E7%BB%93/">
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">

    <link rel="stylesheet" href='/laoer123/css/normalize.css'>
    <link rel="stylesheet" href='/laoer123/css/style.css'>
    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

    
    <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
    <script>
    (adsbygoogle = window.adsbygoogle || []).push({
        google_ad_client: "ca-pub-4031353640611810",
        enable_page_level_ads: true
    });
    </script>
    


    
    
        <link rel="stylesheet" href='/laoer123/css/douban.css'>
    
        <link rel="stylesheet" href='/laoer123/css/other.css'>
    
</head>


<body>
    <header id="header" class="clearfix">
    <div class="container">
        <div class="col-group">
            <div class="site-name ">
                
                    <a id="logo" href="https://laoer123.gitee.io/laoer123">
                        Jeremy Sze的博客
                    </a>
                
                <p class="description">专注于Java、JavaScript、软件开发、web开发、分布式，微服务系统开发</p>
            </div>
            <div>
                <nav id="nav-menu" class="clearfix">
                    <a class="current" href="https://laoer123.gitee.io/laoer123">首页</a>
                    
                    <a  href="https://laoer123.gitee.io/laoer123/about/" title="关于">关于</a>
                    
                </nav>
            </div>
        </div>
    </div>
</header>

    <div id="body">
        <div class="container">
            <div class="col-group">

                <div class="col-8" id="main">
                    
<div class="res-cons">
    <style type="text/css">
    .post-toc {
        position: fixed;
        width: 200px;
        margin-left: -210px;
        padding: 5px 10px;
        font-family: Athelas, STHeiti, Microsoft Yahei, serif;
        font-size: 12px;
        border: 1px solid rgba(0, 0, 0, .07);
        border-radius: 5px;
        background-color: rgba(255, 255, 255, 0.98);
        background-clip: padding-box;
        -webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, .125);
        box-shadow: 1px 1px 2px rgba(0, 0, 0, .125);
        word-wrap: break-word;
        white-space: nowrap;
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
        z-index: 999;
        cursor: pointer;
        max-height: 70%;
        overflow-y: auto;
        overflow-x: hidden;
    }

    .post-toc .post-toc-title {
        width: 100%;
        margin: 0 auto;
        font-size: 20px;
        font-weight: 400;
        text-transform: uppercase;
        text-align: center;
    }

    .post-toc .post-toc-content {
        font-size: 15px;
    }

    .post-toc .post-toc-content>nav>ul {
        margin: 10px 0;
    }

    .post-toc .post-toc-content ul {
        padding-left: 20px;
        list-style: square;
        margin: 0.5em;
        line-height: 1.8em;
    }

    .post-toc .post-toc-content ul ul {
        padding-left: 15px;
        display: none;
    }

    @media print,
    screen and (max-width:1057px) {
        .post-toc {
            display: none;
        }
    }
</style>
<div class="post-toc" style="position: absolute; top: 188px;">
    <h2 class="post-toc-title">文章目录</h2>
    <div class="post-toc-content">
        <nav id="TableOfContents">
  <ul>
    <li><a href="#seata角色成员31">Seata角色成员(3+1)</a></li>
    <li><a href="#at-模式">AT 模式</a>
      <ul>
        <li><a href="#前提">前提</a></li>
      </ul>
    </li>
    <li><a href="#整体机制">整体机制</a></li>
    <li><a href="#写隔离">写隔离</a></li>
    <li><a href="#读隔离">读隔离</a></li>
    <li><a href="#工作机制">工作机制</a></li>
    <li><a href="#一阶段">一阶段</a></li>
    <li><a href="#二阶段-回滚">二阶段-回滚</a></li>
    <li><a href="#二阶段-提交">二阶段-提交</a></li>
  </ul>

  <ul>
    <li><a href="#saga-模式">Saga 模式</a>
      <ul>
        <li><a href="#适用场景">适用场景：</a></li>
        <li><a href="#优势">优势：</a></li>
        <li><a href="#缺点">缺点：</a></li>
      </ul>
    </li>
  </ul>
</nav>
    </div>
</div>
<script type="text/javascript">
    $(document).ready(function () {
        var postToc = $(".post-toc");
        if (postToc.length) {
            var leftPos = $("#main").offset().left;
            if(leftPos<220){
                postToc.css({"width":leftPos-10,"margin-left":(0-leftPos)})
            }

            var t = postToc.offset().top - 20,
                a = {
                    start: {
                        position: "absolute",
                        top: t
                    },
                    process: {
                        position: "fixed",
                        top: 20
                    },
                };
            $(window).scroll(function () {
                var e = $(window).scrollTop();
                e < t ? postToc.css(a.start) : postToc.css(a.process)
            })
        }
    })
</script>
    <article class="post">
        <header>
            <h1 class="post-title">Seata总结</h1>
        </header>
        <date class="post-meta meta-date">
            2022年10月6日
        </date>
        
        <div class="post-meta">
            <span>|</span>
            
            <span class="meta-category"><a href='https://laoer123.gitee.io/categories/SpringCloudAlibaba'>SpringCloudAlibaba</a></span>
            
        </div>
        
        
        <div class="post-meta">
            <span id="busuanzi_container_page_pv">|<span id="busuanzi_value_page_pv"></span><span>
                    阅读</span></span>
        </div>
        
        
        <div class="post-content">
            <h1 id="seata-是什么">Seata 是什么？</h1>
<p>Seata 是一款开源的分布式事务解决方案，致力于在微服务架构下提供高性能和简单易用的分布式事务服务。在 Seata 开源之前，其内部版本在阿里系内部一直扮演着应用架构层数据一致性的中间件角色，帮助经济体平稳的度过历年的双11，对上层业务进行了有力的技术支撑。经过多年沉淀与积累，其商业化产品先后在阿里云、金融云上售卖。2019.1 为了打造更加完善的技术生态和普惠技术成果，Seata 正式宣布对外开源，未来 Seata 将以社区共建的形式帮助用户快速落地分布式事务解决方案。<br>
Seata 是一款开源的分布式事务解决方案，致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式，为用户打造一站式的分布式解决方案。 <br>
<img src="/img/seata1.png" alt="alt seata1"></p>
<h2 id="seata角色成员31">Seata角色成员(3+1)</h2>
<p>**TM:事务的发起者，事务管理器，从代码角度上看，方法上被注解$\color{blue}{@GloalTransactional}$标记的方法为事务发起者,定义全局事务的范围：开始全局事务、提交或回滚全局事务。<br>
**RM:事务参与方，资源管理者,数据库,管理分支事务处理的资源，与TC交谈以注册分支事务和报告分支事务的状态，并驱 动分支事务提交或回滚。<br>
**TC:事务协调者,维护全局和分支事务的状态，驱动全局事务提交或回滚。
**XID:@GloalTransactional，开启全局事务之后，向TC注册TM，TC返回XID
<img src="/img/seata13.png" alt="alt seata13">	
1、服务A启动时，GlobalTransactionScanner会对有@GlobalTransaction注解的方法进行AOP增强，并生成代理，增强的代码位于GlobalTransactionalInterceptor类中，当调用@GlobalTransaction注解的方法时，增强代码首先向TC注册全局事务，表示全局事务的开始，同时TC生成XID，并返回给TM；<br>
2、服务A中调用服务B时，将XID传递给服务B； <br>
3、服务B得到XID后，访问TC，注册分支事务，并从TC获得分支事务ID，TC根据XID将分支事务与全局事务关联； <br>
4、接下来服务B开始执行SQL语句，在执行前将表中对应的数据保存一份，执行后在保存一份，将这两份记录作为回滚记录写入到数据库中，如果执行过程中没有异常，服务B最后将事务提交，并通知TC分支事务成功，服务B也会清除本地事务数据；<br>
5、服务A访问完服务B后，访问服务C；<br>
6、服务C与TC之间的交互与服务B完全一致；<br>
7、服务B和服务C都成功后，服务A通过TM通知TC全局事务成功，如果失败了，服务A也会通知TC全局事务失败；<br>
8、TC记录了全局事务下的每个分支事务，TC收到全局事务的结果后，如果结果成功，则通知RM成功，RM收到通知后清理之前在数据库中保存的回滚记录，如果失败了，则RM要查询出之前在数据库保存的回滚记录，对之前的SQL操作进行回滚。</p>
<p>因为TM、RM、TC之间的交互都是通过网络完成的，很容易出现网络断开的情况，因此TC提供了四个定时线程池，定时检测系统中是否有超时事务、异步提交事务、回滚重试事务、重试提交事务，如果发现了有这四类事务，则从全局事务中获取所有的分支事务，分别调用各个分支事务完成对应的操作，依次来确保事务的一致性。<br>
需要考虑的问题：<br>
通过上面流程的分析可以发现，每次SQL操作（查询除外）时，都会增加额外了三次数据库操作；每次全局事务和分支事务开启时，都涉及到TM、RM与TC的交互；全局事务期间还要承担数据短时不一致的情况，这些都是我们在使用AT模式需要考虑的情况。</p>
<p><img src="/img/seata7.png" alt="alt seata7">	
<img src="/img/seata8.png" alt="alt seata8">	
<img src="/img/seata9.png" alt="alt seata9">	
<img src="/img/seata10.png" alt="alt seata10">	
<img src="/img/seata11.png" alt="alt seata11">	
<img src="/img/seata12.png" alt="alt seata12"></p>
<h2 id="at-模式">AT 模式</h2>
<h3 id="前提">前提</h3>
<ol>
<li>基于支持本地 ACID 事务的关系型数据库。</li>
<li>Java 应用，通过 JDBC 访问数据库。</li>
</ol>
<h2 id="整体机制">整体机制</h2>
<p>两阶段提交协议的演变：</p>
<ol>
<li>一阶段：业务数据和回滚日志记录在同一个本地事务中提交，释放本地锁和连接资源。</li>
<li>二阶段：<br>
  提交异步化，非常快速地完成。<br>
  回滚通过一阶段的回滚日志进行反向补偿。</li>
</ol>
<h2 id="写隔离">写隔离</h2>
<p>**一阶段本地事务提交前，需要确保先拿到全局锁 。<br>
**拿不到全局锁 ，不能提交本地事务。<br>
**拿全局锁的尝试被限制在一定范围内，超出范围将放弃，并回滚本地事务，释放本地锁。<br>
以一个示例来说明：<br>
两个全局事务 tx1 和 tx2，分别对 a 表的 m 字段进行更新操作，m 的初始值 1000。</p>
<p>tx1 先开始，开启本地事务，拿到本地锁，更新操作 m = 1000 - 100 = 900。本地事务提交前，先拿到该记录的 全局锁 ，本地提交释放本地锁。 tx2 后开始，开启本地事务，拿到本地锁，更新操作 m = 900 - 100 = 800。本地事务提交前，尝试拿该记录的 全局锁 ，tx1 全局提交前，该记录的全局锁被 tx1 持有，tx2 需要重试等待 全局锁 。<br>
<img src="/img/seata2.png" alt="alt seata2">	
tx1 二阶段全局提交，释放 全局锁 。tx2 拿到 全局锁 提交本地事务。<br>
<img src="/img/seata3.png" alt="alt seata3">	
如果 tx1 的二阶段全局回滚，则 tx1 需要重新获取该数据的本地锁，进行反向补偿的更新操作，实现分支的回滚。<br>
此时，如果 tx2 仍在等待该数据的 全局锁，同时持有本地锁，则 tx1 的分支回滚会失败。分支的回滚会一直重试，直到 tx2 的 全局锁 等锁超时，放弃 全局锁 并回滚本地事务释放本地锁，tx1 的分支回滚最终成功。<br>
因为整个过程 全局锁 在 tx1 结束前一直是被 tx1 持有的，所以不会发生 脏写 的问题。</p>
<h2 id="读隔离">读隔离</h2>
<p>在数据库本地事务隔离级别 读已提交（Read Committed） 或以上的基础上，Seata（AT 模式）的默认全局隔离级别是 读未提交（Read Uncommitted） 。<br>
如果应用在特定场景下，必需要求全局的 读已提交 ，目前 Seata 的方式是通过 SELECT FOR UPDATE 语句的代理。<br>
在数据库本地事务隔离级别 读已提交（Read Committed） 或以上的基础上，Seata（AT 模式）的默认全局隔离级别是 读未提交（Read Uncommitted） 。<br>
如果应用在特定场景下，必需要求全局的 读已提交 ，目前 Seata 的方式是通过 SELECT FOR UPDATE 语句的代理。<br>
<img src="/img/seata4.png" alt="alt seata4">	
SELECT FOR UPDATE 语句的执行会申请 全局锁 ，如果 全局锁 被其他事务持有，则释放本地锁（回滚 SELECT FOR UPDATE 语句的本地执行）并重试。这个过程中，查询是被 block 住的，直到 全局锁 拿到，即读取的相关数据是 已提交 的，才返回。<br>
出于总体性能上的考虑，Seata 目前的方案并没有对所有 SELECT 语句都进行代理，仅针对 FOR UPDATE 的 SELECT 语句。</p>
<h2 id="工作机制">工作机制</h2>
<p>以一个示例来说明整个 AT 分支的工作过程。<br>
业务表：product</p>
<div class="highlight"><div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-txt" data-lang="txt">Field	Type	Key
id	bigint(20)	PRI
name	varchar(100)	
since	varchar(100)	
</code></pre></td></tr></table>
</div>
</div><p>AT 分支事务的业务逻辑：</p>
<div class="highlight"><div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sql" data-lang="sql"><span style="color:#000;font-weight:bold">update</span> product <span style="color:#000;font-weight:bold">set</span> name <span style="color:#000;font-weight:bold">=</span> <span style="color:#d14">&#39;GTS&#39;</span> <span style="color:#000;font-weight:bold">where</span> name <span style="color:#000;font-weight:bold">=</span> <span style="color:#d14">&#39;TXC&#39;</span>;
</code></pre></td></tr></table>
</div>
</div><h2 id="一阶段">一阶段</h2>
<p>过程：</p>
<ol>
<li>解析 SQL：得到 SQL 的类型（UPDATE），表（product），条件（where name = &lsquo;TXC&rsquo;）等相关的信息。</li>
<li>查询前镜像：根据解析得到的条件信息，生成查询语句，定位数据。</li>
</ol>
<div class="highlight"><div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sql" data-lang="sql"><span style="color:#000;font-weight:bold">select</span> id, name, since <span style="color:#000;font-weight:bold">from</span> product <span style="color:#000;font-weight:bold">where</span> name <span style="color:#000;font-weight:bold">=</span> <span style="color:#d14">&#39;TXC&#39;</span>;
</code></pre></td></tr></table>
</div>
</div><p>得到前镜像：</p>
<div class="highlight"><div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-txt" data-lang="txt">id	name	since
1	TXC		2014
</code></pre></td></tr></table>
</div>
</div><ol start="3">
<li>执行业务 SQL：更新这条记录的 name 为 &lsquo;GTS&rsquo;。</li>
<li>查询后镜像：根据前镜像的结果，通过 主键 定位数据。</li>
</ol>
<div class="highlight"><div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sql" data-lang="sql"><span style="color:#000;font-weight:bold">select</span> id, name, since <span style="color:#000;font-weight:bold">from</span> product <span style="color:#000;font-weight:bold">where</span> id <span style="color:#000;font-weight:bold">=</span> <span style="color:#099">1</span>;
</code></pre></td></tr></table>
</div>
</div><p>得到后镜像：</p>
<div class="highlight"><div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-txt" data-lang="txt">id	name	since
1	GTS		2014
</code></pre></td></tr></table>
</div>
</div><ol start="5">
<li>插入回滚日志：把前后镜像数据以及业务 SQL 相关的信息组成一条回滚日志记录，插入到 UNDO_LOG 表中。</li>
</ol>
<div class="highlight"><div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">34
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">35
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">36
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">37
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">38
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">39
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">40
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">41
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">42
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">43
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-json" data-lang="json">{
	<span style="color:#000080">&#34;branchId&#34;</span>: <span style="color:#099">641789253</span>,
	<span style="color:#000080">&#34;undoItems&#34;</span>: [{
		<span style="color:#000080">&#34;afterImage&#34;</span>: {
			<span style="color:#000080">&#34;rows&#34;</span>: [{
				<span style="color:#000080">&#34;fields&#34;</span>: [{
					<span style="color:#000080">&#34;name&#34;</span>: <span style="color:#d14">&#34;id&#34;</span>,
					<span style="color:#000080">&#34;type&#34;</span>: <span style="color:#099">4</span>,
					<span style="color:#000080">&#34;value&#34;</span>: <span style="color:#099">1</span>
				}, {
					<span style="color:#000080">&#34;name&#34;</span>: <span style="color:#d14">&#34;name&#34;</span>,
					<span style="color:#000080">&#34;type&#34;</span>: <span style="color:#099">12</span>,
					<span style="color:#000080">&#34;value&#34;</span>: <span style="color:#d14">&#34;GTS&#34;</span>
				}, {
					<span style="color:#000080">&#34;name&#34;</span>: <span style="color:#d14">&#34;since&#34;</span>,
					<span style="color:#000080">&#34;type&#34;</span>: <span style="color:#099">12</span>,
					<span style="color:#000080">&#34;value&#34;</span>: <span style="color:#d14">&#34;2014&#34;</span>
				}]
			}],
			<span style="color:#000080">&#34;tableName&#34;</span>: <span style="color:#d14">&#34;product&#34;</span>
		},
		<span style="color:#000080">&#34;beforeImage&#34;</span>: {
			<span style="color:#000080">&#34;rows&#34;</span>: [{
				<span style="color:#000080">&#34;fields&#34;</span>: [{
					<span style="color:#000080">&#34;name&#34;</span>: <span style="color:#d14">&#34;id&#34;</span>,
					<span style="color:#000080">&#34;type&#34;</span>: <span style="color:#099">4</span>,
					<span style="color:#000080">&#34;value&#34;</span>: <span style="color:#099">1</span>
				}, {
					<span style="color:#000080">&#34;name&#34;</span>: <span style="color:#d14">&#34;name&#34;</span>,
					<span style="color:#000080">&#34;type&#34;</span>: <span style="color:#099">12</span>,
					<span style="color:#000080">&#34;value&#34;</span>: <span style="color:#d14">&#34;TXC&#34;</span>
				}, {
					<span style="color:#000080">&#34;name&#34;</span>: <span style="color:#d14">&#34;since&#34;</span>,
					<span style="color:#000080">&#34;type&#34;</span>: <span style="color:#099">12</span>,
					<span style="color:#000080">&#34;value&#34;</span>: <span style="color:#d14">&#34;2014&#34;</span>
				}]
			}],
			<span style="color:#000080">&#34;tableName&#34;</span>: <span style="color:#d14">&#34;product&#34;</span>
		},
		<span style="color:#000080">&#34;sqlType&#34;</span>: <span style="color:#d14">&#34;UPDATE&#34;</span>
	}],
	<span style="color:#000080">&#34;xid&#34;</span>: <span style="color:#d14">&#34;xid:xxx&#34;</span>
}
</code></pre></td></tr></table>
</div>
</div><ol start="6">
<li>提交前，向 TC 注册分支：申请 product 表中，主键值等于 1 的记录的全局锁 。</li>
<li>本地事务提交：业务数据的更新和前面步骤中生成的 UNDO LOG 一并提交。</li>
<li>将本地事务提交的结果上报给 TC。</li>
</ol>
<h2 id="二阶段-回滚">二阶段-回滚</h2>
<ol>
<li>收到 TC 的分支回滚请求，开启一个本地事务，执行如下操作。</li>
<li>通过 XID 和 Branch ID 查找到相应的 UNDO LOG 记录。</li>
<li>数据校验：拿 UNDO LOG 中的后镜与当前数据进行比较，如果有不同，说明数据被当前全局事务之外的动作做了修改。这种情况，需要根据配置策略来做处理，详细的说明在另外的文档中介绍。</li>
<li>根据 UNDO LOG 中的前镜像和业务 SQL 的相关信息生成并执行回滚的语句：</li>
</ol>
<div class="highlight"><div style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sql" data-lang="sql"><span style="color:#000;font-weight:bold">update</span> product <span style="color:#000;font-weight:bold">set</span> name <span style="color:#000;font-weight:bold">=</span> <span style="color:#d14">&#39;TXC&#39;</span> <span style="color:#000;font-weight:bold">where</span> id <span style="color:#000;font-weight:bold">=</span> <span style="color:#099">1</span>;
</code></pre></td></tr></table>
</div>
</div><ol start="5">
<li>提交本地事务。并把本地事务的执行结果（即分支事务回滚的结果）上报给 TC。</li>
</ol>
<h2 id="二阶段-提交">二阶段-提交</h2>
<ol>
<li>收到TC的分支提交请求，把请求放入一个异步任务的队列中，马上返回提交成功的结果给TC。</li>
<li>异步任务阶段的分支提交请求将异步和批量地删除相应 UNDO LOG 记录。</li>
</ol>
<h1 id="tcc-模式">TCC 模式</h1>
<p>回顾总览中的描述：一个分布式的全局事务，整体是 两阶段提交 的模型。全局事务是由若干分支事务组成的，分支事务要满足 两阶段提交 的模型要求，即需要每个分支事务都具备自己的：</p>
<ol>
<li>一阶段 prepare 行为</li>
<li>二阶段 commit 或 rollback 行为<br>
<img src="/img/seata5.png" alt="alt seata5">	
根据两阶段行为模式的不同，我们将分支事务划分为 Automatic (Branch) Transaction Mode 和 Manual (Branch) Transaction Mode.<br>
AT 模式（参考链接 TBD）基于 支持本地 ACID 事务 的 关系型数据库：<br>
一阶段 prepare 行为：在本地事务中，一并提交业务数据更新和相应回滚日志记录。<br>
二阶段 commit 行为：马上成功结束，自动 异步批量清理回滚日志。<br>
二阶段 rollback 行为：通过回滚日志，自动 生成补偿操作，完成数据回滚。</li>
</ol>
<p>相应的，TCC 模式，不依赖于底层数据资源的事务支持：<br>
一阶段 prepare 行为：调用 自定义 的 prepare 逻辑。<br>
二阶段 commit 行为：调用 自定义 的 commit 逻辑。<br>
二阶段 rollback 行为：调用 自定义 的 rollback 逻辑。<br>
所谓 TCC 模式，是指支持把 自定义 的分支事务纳入到全局事务的管理中。</p>
<h2 id="saga-模式">Saga 模式</h2>
<p>Saga模式是SEATA提供的长事务解决方案，在Saga模式中，业务流程中每个参与者都提交本地事务，当出现某一个参与者失败则补偿前面已经成功的参与者，一阶段正向服务和二阶段补偿服务都由业务开发实现。<br>
<img src="/img/seata6.png" alt="alt seata6"></p>
<h3 id="适用场景">适用场景：</h3>
<ol>
<li>业务流程长、业务流程多</li>
<li>参与者包含其它公司或遗留系统服务，无法提供 TCC 模式要求的三个接口</li>
</ol>
<h3 id="优势">优势：</h3>
<ol>
<li>一阶段提交本地事务，无锁，高性能</li>
<li>事件驱动架构，参与者可异步执行，高吞吐</li>
<li>补偿服务易于实现</li>
</ol>
<h3 id="缺点">缺点：</h3>
<p>不保证隔离性</p>

        </div>

        
<div class="post-archive">
    <ul class="post-copyright">
        <li><strong>原文作者：</strong><a rel="author" href="https://laoer123.gitee.io/laoer123">Jeremy Sze</a></li>
        <li style="word-break:break-all"><strong>原文链接：</strong><a href="https://laoer123.gitee.io/laoer123/post/Seata%E6%80%BB%E7%BB%93/">https://laoer123.gitee.io/laoer123/post/Seata%E6%80%BB%E7%BB%93/</a></li>
        <li><strong>版权声明：</strong>本作品采用<a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/">知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议</a>进行许可，非商业转载请注明出处（作者，原文链接），商业转载请联系作者获得授权。</li>
    </ul>
</div>
<br/>



        

<div class="post-archive">
    <h2>See Also</h2>
    <ul class="listing">
        
        <li><a href="/laoer123/post/OpenFegin%E6%80%BB%E7%BB%93/">OpenFegin总结</a></li>
        
        <li><a href="/laoer123/post/SpringCloudRibbon/">SpringCloudRibbon总结</a></li>
        
        <li><a href="/laoer123/post/SpringCloudGateWay%E6%80%BB%E7%BB%93/">SpringCloudGateWay总结</a></li>
        
        <li><a href="/laoer123/post/Nacos%E6%80%BB%E7%BB%93/">什么是Nacos</a></li>
        
        <li><a href="/laoer123/post/Nacos%E9%85%8D%E7%BD%AE%E6%B3%A8%E5%86%8C%E4%B8%8E%E5%8F%91%E7%8E%B0/">Nacos配置注册与发现</a></li>
        
    </ul>
</div>


        <div class="post-meta meta-tags">
            
            <ul class="clearfix">
                
                <li><a href='https://laoer123.gitee.io/tags/Seata'>Seata</a></li>
                
            </ul>
            
        </div>
    </article>
    
    <div id="disqus_thread"></div>
<script type="application/javascript">
    var disqus_config = function () {
    
    
    
    };
    (function() {
        if (["localhost", "127.0.0.1"].indexOf(window.location.hostname) != -1) {
            document.getElementById('disqus_thread').innerHTML = 'Disqus comments not available by default when the website is previewed locally.';
            return;
        }
        var d = document, s = d.createElement('script'); s.async = true;
        s.src = '//' + "yourdiscussshortname" + '.disqus.com/embed.js';
        s.setAttribute('data-timestamp', +new Date());
        (d.head || d.body).appendChild(s);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="https://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

    
    
</div>

                </div>

                <div id="secondary">
    <section class="widget">
        <form id="search" action='https://laoer123.gitee.io/laoer123/search/' method="get" accept-charset="utf-8" target="_blank" _lpchecked="1">
      
      <input type="text" name="q" maxlength="20" placeholder="Search">
      <input type="hidden" name="sitesearch" value="https://laoer123.gitee.io/laoer123">
      <button type="submit" class="submit icon-search"></button>
</form>
    </section>
    
    <section class="widget">
        <h3 class="widget-title">最近文章</h3>
<ul class="widget-list">
    
    <li>
        <a href="https://laoer123.gitee.io/laoer123/post/springcloud%E4%B8%8EspringcloudAlibaba%E6%80%BB%E7%BB%93/" title="springcloud与springcloudAlibaba总结">springcloud与springcloudAlibaba总结</a>
    </li>
    
    <li>
        <a href="https://laoer123.gitee.io/laoer123/post/Seata%E6%80%BB%E7%BB%93/" title="Seata总结">Seata总结</a>
    </li>
    
    <li>
        <a href="https://laoer123.gitee.io/laoer123/post/OpenFegin%E6%80%BB%E7%BB%93/" title="OpenFegin总结">OpenFegin总结</a>
    </li>
    
    <li>
        <a href="https://laoer123.gitee.io/laoer123/post/SpringCloudGateWay%E6%80%BB%E7%BB%93/" title="SpringCloudGateWay总结">SpringCloudGateWay总结</a>
    </li>
    
    <li>
        <a href="https://laoer123.gitee.io/laoer123/post/SpringCloudRibbon/" title="SpringCloudRibbon总结">SpringCloudRibbon总结</a>
    </li>
    
    <li>
        <a href="https://laoer123.gitee.io/laoer123/post/Nacos%E9%85%8D%E7%BD%AE%E6%B3%A8%E5%86%8C%E4%B8%8E%E5%8F%91%E7%8E%B0/" title="Nacos配置注册与发现">Nacos配置注册与发现</a>
    </li>
    
    <li>
        <a href="https://laoer123.gitee.io/laoer123/post/Nacos%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86%E6%BC%94%E7%A4%BA/" title="Nacos配置管理演示">Nacos配置管理演示</a>
    </li>
    
    <li>
        <a href="https://laoer123.gitee.io/laoer123/post/Nacos%E6%80%BB%E7%BB%93/" title="什么是Nacos">什么是Nacos</a>
    </li>
    
    <li>
        <a href="https://laoer123.gitee.io/laoer123/post/Sentinel%E6%96%B0%E6%89%8B%E6%8C%87%E5%8D%97/" title="Sentinel新手指南">Sentinel新手指南</a>
    </li>
    
    <li>
        <a href="https://laoer123.gitee.io/laoer123/post/Sentinel%E6%8E%A7%E5%88%B6%E5%8F%B0/" title="Sentinel控制台">Sentinel控制台</a>
    </li>
    
</ul>
    </section>

    

    <section class="widget">
        <h3 class="widget-title">分类</h3>
<ul class="widget-list">
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/Linux/">Linux (2)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/NoSql%E6%95%B0%E6%8D%AE%E5%BA%93/">NoSql数据库 (1)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/SpringCloud/">SpringCloud (2)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/SpringCloudAlibaba/">SpringCloudAlibaba (11)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/SpringCloudAlibabaSpringCloud/">SpringCloudAlibaba,SpringCloud (1)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/docker/">docker (2)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/java%E5%9F%BA%E7%A1%80/">java基础 (10)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/spring/">spring (4)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/%E4%BA%8B%E5%8A%A1/">事务 (1)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/%E5%88%86%E5%B8%83%E5%BC%8F/">分布式 (1)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/%E5%89%8D%E7%AB%AF%E5%BE%AE%E6%9C%8D%E5%8A%A1/">前端微服务 (1)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/">前端框架 (2)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/%E6%8C%81%E7%BB%AD%E9%9B%86%E6%88%90/">持续集成 (1)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E/">搜索引擎 (1)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/%E6%95%B0%E6%8D%AE%E5%B1%82%E6%A1%86%E6%9E%B6/">数据层框架 (1)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/">数据库 (5)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/%E6%9C%8D%E5%8A%A1%E5%99%A8/">服务器 (1)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/%E6%9E%B6%E6%9E%84/">架构 (1)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6/">消息中间件 (1)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6/">版本控制 (1)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/%E7%BC%93%E5%AD%98/">缓存 (1)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/%E8%AE%A4%E8%AF%81/">认证 (2)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/%E8%BF%90%E7%BB%B4/">运维 (1)</a></li>
    
    <li><a href="https://laoer123.gitee.io/laoer123/categories/%E9%83%A8%E7%BD%B2/">部署 (1)</a></li>
    
</ul>
    </section>

    <section class="widget">
        <h3 class="widget-title">标签</h3>
<div class="tagcloud">
    
    <a href="https://laoer123.gitee.io/laoer123/tags/Dubbo/">Dubbo</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/ES6/">ES6</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/ElasticSearch/">ElasticSearch</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/ElementUI/">ElementUI</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/Eureka/">Eureka</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/Feign/">Feign</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/JDBCTemplate/">JDBCTemplate</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/JPA/">JPA</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/JWT/">JWT</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/Jenkins/">Jenkins</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/Linux%E5%9F%BA%E7%A1%80/">Linux基础</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/Linux%E9%85%8D%E7%BD%AE%E8%81%94%E7%BD%91/">Linux配置联网</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/MongoDB/">MongoDB</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/Nacos/">Nacos</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/ORACLE/">ORACLE</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/OpenFegin/">OpenFegin</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/RabbitMQ/">RabbitMQ</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/Seata/">Seata</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/Sentinel/">Sentinel</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/SpringCloudGateWay/">SpringCloudGateWay</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/SpringCloudRibbon/">SpringCloudRibbon</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/SpringCloudSpringCloudAlibaba/">SpringCloud,SpringCloudAlibaba</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/VUE/">VUE</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/docker/">docker</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/git/">git</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/gogs/">gogs</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/hystrix/">hystrix</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/mysql/">mysql</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/nginx/">nginx</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/nodeJS/">nodeJS</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/npm/">npm</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/springCache/">springCache</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/springDataJPA/">springDataJPA</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/springboot/">springboot</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/springcloudbus/">springcloudbus</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/springcloudconfig/">springcloudconfig</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/springdataredis/">springdataredis</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/zuul/">zuul</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/%E5%88%86%E5%B8%83%E5%BC%8F/">分布式</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/">分布式事务</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/%E5%88%9B%E5%BB%BA%E6%A8%A1%E5%BC%8F/">创建模式</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/%E5%BE%AE%E6%9C%8D%E5%8A%A1/">微服务</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/%E6%8E%92%E5%BA%8F/">排序</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/%E6%9C%8D%E5%8A%A1%E9%95%9C%E5%83%8F%E7%9A%84%E6%9E%84%E5%BB%BA%E4%B8%8E%E9%83%A8%E7%BD%B2/">服务镜像的构建与部署</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/%E7%BB%93%E6%9E%84%E6%A8%A1%E5%BC%8F/">结构模式</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/%E8%A1%8C%E4%B8%BA%E6%A8%A1%E5%BC%8F/">行为模式</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/">设计模式</a>
    
    <a href="https://laoer123.gitee.io/laoer123/tags/%E8%BF%90%E7%BB%B4/">运维</a>
    
</div>
    </section>

    
<section class="widget">
    <h3 class="widget-title">友情链接</h3>
    <ul class="widget-list">
        
        <li>
            <a target="_blank" href="https://www.cnblogs.com/Jeremy95-Sze/" title="Jeremy Sze的博客">Jeremy Sze的博客</a>
        </li>
        
        <li>
            <a target="_blank" href="https://github.com/Jeremy95-Sze" title="Jeremy Sze的github">Jeremy Sze的github</a>
        </li>
        
    </ul>
</section>


    <section class="widget">
        <h3 class="widget-title">其它</h3>
        <ul class="widget-list">
            <li><a href="https://laoer123.gitee.io/laoer123/index.xml">文章 RSS</a></li>
        </ul>
    </section>
</div>
            </div>
        </div>
    </div>
    <footer id="footer">
    <div class="container">
        &copy; 2023 <a href="https://laoer123.gitee.io/laoer123">Jeremy Sze的博客 By Jeremy Sze</a>.
        Powered by <a rel="nofollow noreferer noopener" href="https://gohugo.io" target="_blank">Hugo</a>.
        <a href="https://www.flysnow.org/" target="_blank">Theme</a> based on <a href="https://github.com/flysnow-org/maupassant-hugo" target="_blank">maupassant</a>.
        
    </div>
</footer>


    
    <script src="//cdnjs.cloudflare.com/ajax/libs/webfont/1.6.28/webfontloader.js" crossorigin="anonymous"></script>
        <script src="//cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js" crossorigin="anonymous"></script>
        <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js" crossorigin="anonymous"></script>
        <script src="//cdnjs.cloudflare.com/ajax/libs/js-sequence-diagrams/1.0.6/sequence-diagram-min.js" crossorigin="anonymous"></script>
        <script>(function () {
            if (!window.Diagram) return;
            const blocks = document.querySelectorAll('pre code.language-sequence');
            for (let i = 0; i < blocks.length; i++) {
                const block = blocks[i];
                
                const rootElement = block.parentNode;
                const container = document.createElement('div');
                const id = `js-sequence-diag-${i}`;
                container.id = id;
                container.className = 'align-center';
                container.setAttribute("style", "overFlow-x:auto");
                rootElement.parentNode.replaceChild(container, rootElement);

                const diagram = Diagram.parse(block.childNodes[0].nodeValue);
                diagram.drawSVG(id, window.sequenceDiagramsOptions
                    ? window.sequenceDiagramsOptions
                    : { theme: 'simple' });
            }
        })();
        </script><script type="text/javascript">
        window.MathJax = {
            tex2jax: {
                inlineMath: [['$', '$']],
                processEscapes: true
                }
            };
    </script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML' async></script>


<a id="rocket" href="#top"></a>
<script type="text/javascript" src='/laoer123/js/totop.js?v=0.0.0' async=""></script>

<script type="application/javascript">
var doNotTrack = false;
if (!doNotTrack) {
	window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
	ga('create', 'GA ID', 'auto');
	
	ga('send', 'pageview');
}
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>



    <script type="text/javascript" src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" async></script>




    <script src='/laoer123/js/douban.js'></script>

</body>

</html>